﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PerCederberg.Grammatica.Runtime;

namespace SafeScript.MetaModel
{
    public class MemberFunction : FunctionTypeDef, INamed, IMember
    {
        public string Name { get; set; }
        public List<Parameter> Parameters = new List<Parameter>();
        public Statements.StatementList Statements;
        public Namespace Owner;
        public bool IsOverride;
        public bool IsSealed;
        public bool IsAbstract;
        public bool IsIterator;
        public List<Statements.VarStatement> Variables = new List<SafeScript.MetaModel.Statements.VarStatement>();
        /// <summary>
        /// May be null.
        /// </summary>
        public MemberFunction Template;

        /// <summary>
        /// May be null.
        /// </summary>
        public MemberAttribute[] Attributes { get; set; }

        /// <summary>
        /// May be null.
        /// </summary>
        public MemberFunction OverridenFunction;

        public virtual void ComputeType(ErrorReport report)
        {
//            List<ITypeDef> p = new List<ITypeDef>();
//            foreach (Parameter pa in this.Parameters)
//                this.ParameterTypes.Add(pa.Type);
        }

        public T GetAttribute<T>() where T : MemberAttribute
        {
            if (this.Attributes == null)
                return null;
            foreach (MemberAttribute attr in this.Attributes)
            {
                if (attr is T)
                    return (T)attr;
            }
            return default(T);
        }

        internal Node Node;
        internal Using Using;

        public override ITypeDef Instantiate(Dictionary<TemplateParameterType,ITypeDef> templateArguments)
        {
            MemberFunction f = new MemberFunction()
            {
                Name = this.Name,
                IsOverride = this.IsOverride,
                IsSealed = this.IsSealed,
                IsAbstract = this.IsAbstract,
                IsIterator = this.IsIterator,
                Template = this,
                Attributes = this.Attributes
            };
            this.InstantiateIntern(f, templateArguments);
            for( int i = 0; i < this.Parameters.Count; ++i )
                f.Parameters.Add(new Parameter() { Name = this.Parameters[i].Name, Type = f.ParameterTypes[i] } );

            return f;
        }
    }

    public class Parameter : INamed
    {
        public string Name { get; set; }
        public ITypeDef Type;
    }
}
